<?php
defined('SYS_IN') OR die('error');
class dbdrive_pdo extends db{
	
	/*
	 * pdo对象 
	 */
	private static $_PDO = null;
	
	/*
	 * sql
	 */
	private $_SQL = null;
	
	/*
	 * result
	 */
	private $_rs = null;
	
	/*
	 * table 
	 */
	private $_table = '';
	
	/*
	 * field
	 */
	private $_field = '';
	
	/*
	 * where
	 */
	private $_where = '';
	
	/*
	 * group
	 */
	private $_group = '';
	
	/*
	 * limit
	 */
	private $_limit = '';
	
	/*
	 * order
	 */
	private $_order = '';
	
	/*
	 * having
	 */
	private $_having = '';
	
	/*
	 * leftJoin
	 */
	private $_leftJoin = '';
	
	/*
	 * lastSql
	 */
	private $_lastSql = '';
	
	/*
	 * param
	 */
	private $_param = array();
	
	public function __construct(){
		$this->connect();
		$this->_setPDO();
	}
	
	/*
	 * set pdo
	 */
	private function _setPDO(){
		//self::$_PDO->setAttribute();
		self::$_PDO->query('set names utf8');
	}
	
	/* 
	 * @see db::connect()
	 */
	public function connect() {
		if(self::$_PDO===null){
			try{
				self::$_PDO = new PDO(C('DB/dsn'),C('DB/user'),C('DB/pwd'));
			}catch(Exception $e){
				echo $e->getMessage();
			}
		}
		return $this;
	}
	
	/*
	 * @see db::table
	 */
	public function table($table){
		$this->_table = $table;
		return $this;
	}
	
	/* 
	 * @see db::query()
	 */
	public function query($sql,$array=array()) {
		return $this->_query($sql,$array)->fetchAll();
	}
	
	/*
	 * query
	 */
	private function _query($sql,$array=array()){
		$this->_lastSql = $sql;
		$this->_rs = self::$_PDO->prepare($sql);
		$this->_rs->execute($array);
		$this->_rs->setFetchMode(PDO::FETCH_ASSOC);
		$this->_error();//错误处理
		return $this->_rs;
	}

	/* 
	 * @see db::where()
	 */
	public function where($where,$param=array()) {
		$this->_where .= empty($this->_where)?' WHERE '.$where:' AND '.$where;
		$this->_param = array_merge($this->_param,$param);
		return $this;
	}
	
	/*
	 * @see db::setColumn
	 */
	public function setColumn($str)
	{
		$this->_field = $str;
		return $this;
	}
	
	/* 
	 * @see db::getOne()
	 */
	public function getOne() {
		$this->limit(0,1);
		return $this->_select();
	}

	/* 
	 * @see db::getAll()
	 */
	public function getAll() {
		return $this->_select();
	}

	/*
	 * @see db::getCount
	 */
	public function getCount()
	{
		$row = $this->_select(true);
		return isset($row[0]['c'])?$row[0]['c']:0;
	}
	
	/*
	 * select
	 */
	private function _select($count=false)
	{
		if($count)//get count
			$field = 'COUNT(1) as c';
		else
			$field = empty($this->_field)?'*':$this->_field;
		$sql = 'SELECT '.$field.' FROM '.$this->_table.$this->_leftJoin.$this->_where.$this->_group.$this->_having.$this->_limit.$this->_order;
		return $this->_query($sql,$this->_param)->fetchAll();
	}

	/* 
	 * @see db::limit()
	 */
	public function limit($start,$size=null) {
		$this->_limit = ' limit '.$start;
		if($size) $this->_limit .= ','.$size;
		return $this;
	}

	/*  
	 * @see db::insert()
	 */	
	public function insert($arr1,$arr2=array())
	{
		$sql_insert = $field = $value = '';
		if(empty($arr2))	//insert one
		{
			foreach($arr1 as $k=>$v)
			{
				$field .= (empty($field)?'`':',`').$k.'`';
				if(is_string($v))
					$value .= (empty($value)?'':',')."'".addslashes($v)."'";
				else
					$value .= (empty($value)?'':',').$v;
			}
			$field = '('.$field.')';
			$value = '('.$value.')';
		}					//insert more
		else
		{
			foreach($arr1 as $v)
			{
				$field .= (empty($field)?'`':',`').$v.'`';
			}
			foreach($arr2 as $vv)
			{
				$value .= empty($value)?'(':',(';
				$field_temp = '';
				foreach($vv as $v)
				{
					if(is_string($v))
						$field_temp .= (empty($field_temp)?'':',')."'".addslashes($v)."'";
					else
						$field_temp .= (empty($field_temp)?'':',').$v;
				}
				$value .= $field_temp.')';
				$field_temp = '';
			}
			$field = '('.$field.')';
		}
		$sql = 'INSERT INTO '.$this->_table.$field.' values '.$value;
		$this->_query($sql);
		return $this->getLastId();
	}

	/*  
	 * @see db::del()
	 */
	public function del() {
		$sql = 'DELETE FROM '.$this->_table.$this->_where;
		return $this->_query($sql,$this->_param)->rowCount();		
	}

	/*  
	 * @see db::update()
	 */
	public function update($array)
	{
		$set = '';
		foreach($array as $k=>$v)
		{
			$set = (empty($set)?'':',')."`{$k}`="."'".addslashes($v)."'";
		}
		$sql = 'UPDATE '.$this->_table.' SET '.$set.$this->_where;
		return $this->_query($sql,$this->_param)->rowCount();
	}

	/*  
	 * @see db::getLastId()
	 */
	public function getLastId() {
		return self::$_PDO->lastInsertId();
	}
	
	/*
	 *  @see db::getLastSql
	 */
	public function getLastSql()
	{
		$sql = $this->_lastSql;
		foreach($this->_param as $k=>$v)
		{
			if(strpos($k,':')===false)
			{
				$pos = strpos($sql,'?');
				if($pos==false) continue;
				$sql = substr_replace($sql,$v,$pos,1);
			}
			else
				$sql = str_ireplace($k,$v,$sql);
		}
		return $sql;
	}
	
	/*
	 * @see db::getError
	 */
	public function getError()
	{
		$rsError  = $this->_rs->errorInfo();
		return array('success'=>empty($rsError[1]),'code'=>$rsError[1],'info'=>$rsError[2],'sql'=>$this->getLastSql());
	}
	
	/*
	 * error
	 */
	private function _error()
	{
		$rsError  = $this->_rs->errorInfo();
		$this->isSuccess = empty($rsError[1]);
		//sql error
		if(!$this->isSuccess)
		{
			echo "sql error:<br/>sql=".$this->getLastSql().'<br/>error:'.$rsError[1].',error='.$rsError[2];
		}
	}
	
	/*
	 * @see db::leftJoin
	 */
	public function leftJoin( $table, $where)
	{
		$this->_leftJoin = ' LEFT JOIN '.$table." ON ({$where}) ";
		return $this;
	}
	/*
	 * @see db::order
	 */	
	public function order($str)
	{
		$this->_order = ' ORDER BY '.$str;
		return $this;
	}
	/*
	 * @see db::groupBy
	 */	
	public function groupBy($str)
	{
		$this->_group = ' GROUP BY '.$str;
		return $this;
	}
	
	/*
	 * @see db::having
	 */
	public function having($where,$param=array())
	{
		$this->_having .= empty($this->_having)?' HAVING '.$where:' AND '.$where;
		$this->_param = array_merge($this->_param,$param);
		return $this;
	}
	
	/*
	 * @see db::begin
	 */
	public function begin()
	{
		return self::$_PDO->beginTransaction();
	}
	
	/*
	 * @see db::rollback
	 */
	public function rollBack()
	{
		return self::$_PDO->rollBack();
	}
	
	/*
	 * @see db::commit
	 */
	public function commit()
	{
		return self::$_PDO->commit();
	}
}
?>
